package utility

import (
	"context"
	"errors"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/golang-jwt/jwt/v4"
	"sync"
	"time"
)

// Claims 自定义 JWT 声明结构体
type Claims struct {
	UserID   uint   `json:"user_id"`
	Username string `json:"username"`
	jwt.RegisteredClaims
}

// GetJWTSecret 获取 JWT 密钥
func GetJWTSecret() []byte {
	ctx := context.Background()
	secret := g.Cfg().MustGet(ctx, "app.jwt_secret").String()
	if secret == "" {
		g.Log().Fatalf(ctx, "JWT secret is not set in config.yaml")
	}
	return []byte(secret)
}

// GenerateToken 生成 JWT token
func GenerateToken(userID uint, userName string) (string, error) {
	// 设置过期时间
	expirationTime := time.Now().Add(24 * time.Hour)

	// 填充 Claims 结构体
	claims := &Claims{
		UserID:   userID,
		Username: userName,
		RegisteredClaims: jwt.RegisteredClaims{
			// 设置过期时间
			ExpiresAt: jwt.NewNumericDate(expirationTime),
		},
	}

	// 创建 JWT 对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 生成签名
	tokenString, err := token.SignedString(GetJWTSecret())
	if err != nil {
		return "", err
	}

	return tokenString, nil
}

// ParseToken 解析 JWT token
func ParseToken(ctx context.Context, tokenString string) (*Claims, error) {
	secret := g.Cfg().MustGet(ctx, "app.jwt_secret").String()
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		// 这里需要替换为你的实际密钥
		return []byte(secret), nil
	})
	if err != nil {
		return nil, err
	}
	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	}
	return nil, errors.New("invalid token")
}

// Blacklist 存储登出的令牌
var blacklist = struct {
	sync.RWMutex
	tokens map[string]time.Time
}{
	tokens: make(map[string]time.Time),
}

// AddToBlacklist 将令牌添加到黑名单
func AddToBlacklist(token string, expiration time.Time) {
	blacklist.Lock()
	defer blacklist.Unlock()
	blacklist.tokens[token] = expiration
}
